package cn.szsys.integration.helper.business.impl;

import cn.szsys.integration.billrule.BillingMapperUtils;
import cn.szsys.integration.billrule.annoation.BillRule;
import cn.szsys.integration.billrule.entity.BillingInfo;
import cn.szsys.integration.constants.BillRuleRecordTypeEnum;
import cn.szsys.integration.constants.EconomicCapabilityConstant;
import cn.szsys.integration.constants.ZxyrResultMapperedEnum;
import cn.szsys.integration.dto.EconomicCapabilityDTO;
import cn.szsys.integration.ex.BusinessException;
import cn.szsys.integration.ex.enums.ExceptionEnum;
import cn.szsys.integration.helper.BusinessBeanNameConstant;
import cn.szsys.integration.helper.business.AbstractEconomicCapabilityHandlerChain;
import cn.szsys.integration.util.EncryptUtil;
import cn.szsys.integration.util.OkHttpUtil;
import cn.szsys.integration.util.R;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * zhongxingyinrong
 *
 * @author Ryan
 * @since 2025-05-12
 **/
@Component(BusinessBeanNameConstant.EconomicCapability.VD_ECONOMIC_CAPABILITY_HANDLER_CHAIN)
@Slf4j
public class VdEconomicCapabilityHandlerChain extends AbstractEconomicCapabilityHandlerChain {

    @Value("${economic-capability.vd.url}")
    private String url;
    @Value("${economic-capability.vd.ak}")
    private String ak;
    @Value("${economic-capability.vd.aks}")
    private String aks;


    /**
     * 转换对应结果并设置计费信息
     *
     * @param obj           obj
     * @param consumingTime consumingTime
     * @return {@link R}
     * @author Ryan
     */
    @Override
    public R<?> convertResultAndBilling(JSONObject obj, long consumingTime) {
        if (Objects.equals("E0000", obj.getString("sysCode"))) {

            String data = obj.getString("data");
            //解密后json数据。
            String decrypt = EncryptUtil.ECB.decode(data, aks);
            log.info("针对VD响应data解密, data decrypt: {}", decrypt);
            //{"status":"200","msg":"成功","num":"c223e130-0671-4caa-a572-50b85fd0965b","timestamp":"1747186957526","data":"mpHGGveDxsjY27vDnzH+O1krbVLwKnyyAMtJZOUFNu1SJaQhc9sZwItdbZvm1WRGJ6aZq+U/yKa8a1mkIFY/zg4ALk+ZZ/ivuqloEfa39zPzzkxTBu8saFPmOi3HuzV9fbOEIgVp5Xv2RnWDKcDP+KPfrPji2MsEmHeKjf3np0iPOQvsRoWrR0ju6YeK7DWsCjz32hcM2ZKQhzBXCfGqZd/IxJBAY3HC9EhgbxwONmoSM9zJ8G+aPZQEd21ueZGU2sKdRG8WM2U+1HSVLbjxda+i0mzCPGBSBKYdhCC7G7oXZt2XI2qyru9daCYp2Hr19hvfYMepwTar5lLKE7VmQQ=="}
            JSONObject dataJson = JSON.parseObject(decrypt);
            if (Objects.equals("200", dataJson.getString("status"))) {
                String resultData = dataJson.getString("data");
                JSONObject resultJson = JSON.parseObject(resultData);
                //设置计费数据
                String code = resultJson.getString("code");
                ZxyrResultMapperedEnum byUpstreamCode = ZxyrResultMapperedEnum.getByUpstreamCode(code);
                BillingInfo billingInfo = BillingInfo.build(byUpstreamCode.getDownstreamCode(), code, consumingTime);
                BillingMapperUtils.set(billingInfo);
                return R.success(resultJson);
            }
        }
        ZxyrResultMapperedEnum byUpstreamCode = ZxyrResultMapperedEnum.NONE;
        BillingInfo billingInfo = BillingInfo.build(byUpstreamCode.getDownstreamCode(), byUpstreamCode.getUpstreamCode(), consumingTime);
        BillingMapperUtils.set(billingInfo);
        return R.error(ExceptionEnum.OP_FAIL);
    }

    /**
     * 执行业务处理
     *
     * @param dto          参数
     * @param reqStartTime reqStartTime
     * @return {@link R}
     * @author Ryan
     */
    @Override
    public R<?> doHandle(EconomicCapabilityDTO dto, long reqStartTime) {
        VdEconomicCapabilityHandlerChain thisChain = (VdEconomicCapabilityHandlerChain) AopContext.currentProxy();
        return switch (dto.getCode()) {
            case EconomicCapabilityConstant.CODE_FIN_CAPACITY_00, EconomicCapabilityConstant.CODE_FIN_CAPACITY_01 ->
                    throw new BusinessException(ExceptionEnum.OP_NOT_SUPPORT);
            case EconomicCapabilityConstant.CODE_FIN_CAPACITY_02 -> thisChain.productThree(dto, reqStartTime);
            default -> R.error(ExceptionEnum.OP_FAIL);
        };
    }


    @BillRule(upstream = "virtualDatasource", billRuleRecordType = BillRuleRecordTypeEnum.DAY, product = "经济能力VD")
    public R<?> productThree(EconomicCapabilityDTO dto, long reqStartTime) {
        return request(dto, reqStartTime);
    }

    /**
     * 发送请求
     *
     * @param dto          dto
     * @param reqStartTime reqStartTime
     * @return {@link R<?>}
     * @author Ryan
     */
    public R<?> request(EconomicCapabilityDTO dto, long reqStartTime) {
        JSONObject businessData = new JSONObject();
        businessData.put("idCard", dto.getIdCard());
        businessData.put("name", dto.getName());
        businessData.put("mobile", dto.getMobile());
        businessData.put("code", CODE_MAP.get(dto.getCode()));

        String req = EncryptUtil.ECB.encode(JSONObject.toJSONString(businessData), aks);
        long startTime = System.currentTimeMillis();
        String time = "" + startTime;
        char[] chs = (ak + time).toCharArray();
        Arrays.sort(chs);
        String sign = URLEncoder.encode(EncryptUtil.ECB.encode(new String(chs), aks), StandardCharsets.UTF_8);
        String requestUrl = String.format(url, sign, time, "si-".concat(time));
        String reqJson = "{\"encryptData\":\"" + req + "\"}";

        log.info("请求VD查询经济能力[请求], body :{}", reqJson);
        OkHttpUtil.OkhttpResponse response = OkHttpUtil.builder()
                .url(requestUrl)
                .post(reqJson)
                .sync();

        long endTime = System.currentTimeMillis();
        log.info("请求VD查询经济能力[响应], response: {}, 请求耗时: {}ms", response.getData(), (endTime - startTime));

        if (response.getSuccess()) {
            JSONObject obj = JSON.parseObject(response.getData());
            return convertResultAndBilling(obj, reqStartTime - startTime);
        }
        throw new BusinessException(ExceptionEnum.OP_FAIL, "请求出错!");
    }
}
